Failed to load URL ‘https://localhost:4321/node_modules/jqueryui/jquery-ui.min.js’ for resource ‘jqueryui’ in component

When you point external to CDN, here is the set up I got it working

“externals”: {

“jquery”: {

“path”: “https://code.jquery.com/jquery-3.3.1.min.js“,

“globalName”: “jquery”

},

“jqueryui”: {

“path”: “https://code.jquery.com/ui/1.12.1/jquery-ui.js“,

“globalName”: “jquery”,

“globalDependencies”: [

“jquery”

]}

},

Sorry, apps are turned off. If you know who runs the server, tell them to enable apps.

  1. Make sure your have Apps enabled in your SharePoint 2019 farm. (Apps enabled in your SharePoint 2019 farm)
  2. The subscription service is not configured in your farm. (Configure Subscription Settings Service Application)
  3. Make sure App Management Service Application is associated with your web application
  4. Chances are you have not configured the App Urls.

the information comes from : https://support.shortpoint.com/

Where is the Office365 talent (OriginatingServer) located?

  1. PS C:\Windows\system32> $UserCredential = Get-Credential
  2. PS C:\Windows\system32> $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.of
    fice365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
  3. PS C:\Windows\system32> Import-PSSession $Session
  4. PS C:\Windows\system32> Get-Mailbox -Identity “Your Mail Address” | fl PrimarySmtpAddress,OriginatingServer
    ,OrganizationId

results:

PrimarySmtpAddress : aaronp@xxxxx.onmicrosoft.com
OriginatingServer : SG2PR04A003DC03.APCPR04A003.prod.outlook.com
OrganizationId : APCPR04A003.prod.outlook.com/Microsoft Exchange Hosted Organizations/xxxxx.onmicrosoft.com –
APCPR04A003.prod.outlook.com/ConfigurationUnits/xxxxx.onmicrosoft.com/Configuration

SharePoint Online RER Configuration and Debugging #2 (ClientContext = NULL)

As for this question, I found the mainly reason is ClientID and ClientSecret. I found sometimes I register a new ClientID and ClientSecret cannot work. So I changed some information format. as follows:

When I register the App, Redirect URI: I give it whole URL ( must include Port Number ) like this   https://XXXXX.azurewebsites.net:443/Pages/SettingSecurity.aspx

before solving the issue, My redirect URI is “https://XXXXX.azurewebsites.net” … I don’t know whether or not this is the mainly problem to influence my code. But finally I sorted it out.

Other Problems are:

AppManifest: When I published the “App for SharePoint”, I didn’t change the Url (~remoteAppUrl ) to the Url of the Production with the port number explicit.

  1. Debugging: <StartPage>~remoteAppUrl/Pages/SettingSecurity.aspx?{StandardTokens}</StartPage>
    Production:   <!–<StartPage>https://XXXXX.azurewebsites.net:443/Pages/SettingSecurity.aspx?{StandardTokens}</StartPage>–>
  2. if you wanna debug it, pay close attention to the following line: ClientId=”*” ( don’t need to add any ClientId, keep * ), on the contrary, if you wanna publish it into the Production, you need to change ” * ” to ID like ( ad95a175-b4bb-481e-b644-526b5f37ae02 )

<AppPrincipal>
<RemoteWebApplication ClientId=”*” />
</AppPrincipal>

Elements.XML: It’s the same with the AppManifest

  1. <UrlAction Url=”~remoteAppUrl/Pages/SettingSecurity.aspx?{StandardTokens}&amp;SPListItemId={ItemId}&amp;SPListId={ListId}&amp;SPSource={Source}&amp;SPListURLDir={ListUrlDir}&amp;SPItemURL={ItemUrl}”/>
  2. <!–<UrlAction Url=”https://XXXXX.azurewebsites.net:443/Pages/SettingSecurity.aspx?{StandardTokens}&amp;SPListItemId={ItemId}&amp;SPListId={ListId}&amp;SPSource={Source}&amp;SPListURLDir={ListUrlDir}&amp;SPItemURL={ItemUrl}”/>–>

 

SharePoint Online RER Configuration and Debugging #1

  • Create Project for Remote Event Receiver

Untitled picture

Step2

  • Need to type “USER ACCOUNT” and “PASSWORD” –> Choose “SharePoint Online” –> “Next”

Step3Step4Step5

  • Change the Properties of the Project (SharePointAddIn1)
    1. Handle Add-in Install –> “True”
    2. Handle Add-in Uninstall –> “True”

Step7

  • When you change the properties ( Handle Add-in Install and Handle Add-in Uninstall ), the VS .NET will add Folder called “Services” and .svc file called “AppEventReceiver.svc” under the services folder automatically. This is for Default Lists or Document Libraries.

Step8

If you wanna create custom List, you need to add Remote Event Receiver on your own for installation ( Because we need some information of the RER ). As below: ( Add Remote Event Receiver )

Step9Step10

Step11Step12

  • Config the AppManifest.xml and Web.Config
    1. <StartPage> … </StartPage> –> Point off the Page of the list or Document Library where the RER will be installed on the SharePoint Online. E.g.
      1. Document Library : Document Library URL
      2. List : List URL
    2. ClientId

Step13

  • Config Permission – AppManifest.xml

Step14

  • Grant Permission to an App: https://spexptw.sharepoint.com/sites/dev/_layouts/15/appinv.aspx
    1. App Id ( the same with the Client Id )
    2. Title: the same with the Title on the (…/_layouts/15/appregnew.aspx)
    3. App Domain: the same with the App Domain on the (…/_layouts/15/appregnew.aspx)
    4. Redirect URI: the same with the Redirect Uri on the (…/_layouts/15/appregnew.aspx)
    5. Permission Request XML ( copy from AppManifest.xml and paste it, then click “OK” ):

<AppPermissionRequests AllowAppOnlyPolicy=”true”>

   <AppPermissionRequest Scope=”http://sharepoint/content/sitecollection&#8221; Right=”FullControl” />

</AppPermissionRequests>

Step15

  • Change Web.Config
    1. ClientId
    2. ClientSecret
  • Add Key ( for debugging )
  • <add key=”RERdebuggingServiceBusUrl” value=”https://?????.servicebus.windows.net/3845660891/3839167270/obj/0c454565-deeb-4a44-b8b6-9cce0ff955e1/Services/AppEventReceiver.svc” />
  • “Key” comes from “string debugEndpoint = System.ServiceModel.OperationContext.Current.Channel.LocalAddress.Uri.ToString(); for Debug

 

 

Step16

  • Config Debug ( Right click on the Project name: SamplePnp ) –> click “Properties”
    1. Microsoft Azure Service Bus connection string ( come from Azure ): Primary Connection String

Step17Step18

  • Open the “AppEventReceiver.svc.cs“, Add some code inside. /// When the event was triggered, the process will JUST get into this program, event though you add Remote Event Receiver for Custom Lists

/// Simple Example: ProcessEvent mean -ing; ProcessOneWayEvent mean -ed

public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)

       {

           SPRemoteEventResult result = new SPRemoteEventResult();

 

           switch (properties.EventType)

           {

               case SPRemoteEventType.AppInstalled:

                   HandleAppInstalled(properties);

                   break;

               case SPRemoteEventType.AppUninstalling:

                   HandleAppUninstalling(properties);

                   break;

               case SPRemoteEventType.ItemDeleting:

                   {

                       result.ErrorMessage = “Enhanced Records Manager prevents classes / folders / parts or records being deleted” +

                           “, you must use a disposal to remove them.”;

                       result.Status = SPRemoteEventServiceStatus.CancelWithError;

                       break;

                   }

           }

           return result;

       }

  • Done

{ Question } : If you use the RER for Item deleting

  1. Problem is that when you delete the item all you get is a blank screen when you do it from a list view.
  2. The delete is stopped but no message displayed just a blank screen.
  3. However when you do it from the View Properties page then the delete is stopped and the error message is displayed.

{ Answer } : So now when you install our app it checks for the Minimal Download Strategy ( Site Feature ) and if its activated then deactivates it.

From <https://simpleinnovationassociates.wordpress.com/2015/02/13/display-error-message-from-an-office-365-sharepoint-online-remote-event-receiver/>

Minimal Download Strategy

A technique that delivers a faster and more fluid page navigation experience, in pages and site templates that support it, by downloading and rendering only those portions of a page that are changing.

The product requires Microsoft .Net Framework 4.5

  1. Confirm the .Net Version | Open PowerShell and run the following command.
    • Set-Location ‘HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client’.
    • Get-ItemProperty -Path . | Select-Object Version.
  2. Open Windows Update and find the KB number (KB3102467)  in Microsoft .NET Framework 4.6.1 for Windows Server 2012 R2 for x64 then Uninstall it.
  3. Restarting the server and confirm the .Net Version again | Open PowerShell and run the following command.
    • Set-Location ‘HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client’.
    • Get-ItemProperty -Path . | Select-Object Version.
  4. Done

Permission List, Event Handler

using System;
using System.Globalization;
using System.ComponentModel;
using System.IO;
using System.Data;
using System.Text;
using System.Xml;
using System.Collections;
using System.Configuration;
using System.Diagnostics;
using System.Web;
using System.Security;
using System.Security.Policy;
using System.Security.Principal;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;
namespace SharePointTips.SharePoint.Samples.EventHandlers
{
    /// <summary>
    /// This is the event receiver that traps the item added event of the sharepoint list it is attached to.
    /// </summary>
    class ListItemSecuritySetter:SPItemEventReceiver
    {
        #region constants
        /// <summary>
        /// defines the permission set for editors. 
        /// </summary>
        const SPBasePermissions c_EditorPermissions = SPBasePermissions.EditListItems | SPBasePermissions.ViewListItems;
        /// <summary>
        /// defines the permission set for readers
        /// </summary>
        const SPBasePermissions c_ReaderPermissions = SPBasePermissions.ViewListItems;
        /// <summary>
        /// The name of the role that will be created for the author
        /// </summary>
        const string c_AuthorRoleName = “Item Author and Editor”;
        /// <summary>
        /// The name of the role that will be created for the reader
        /// </summary>
        const string c_ReaderRoleName = “Item Reader”;
        /// <summary>
        /// Debug mode writes almost every action to the file log. In production switch this to false. Recommend changing that to read from a configuration file
        /// </summary>
        const bool DEBUG_MODE = true;
        /// <summary>
        /// The page where the log file will be created. Recommend changing that to read from a configuration file
        /// </summary>
        const string c_logFileFolder = @”c:\temp”;        
        #endregion

        #region class properties
        /// <summary>
        /// Returns the name of the log file to be used (file name only – not path)
        /// The string returned will contain {0} and {1} that should be replaced with list name and site name.
        /// </summary>
        private string LogFileName
        {
            get
            {
                return “ListItemSecuritySetter-{0}-{1}-” + DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + “.htm”;
            }
        }

        #endregion

        #region local variables

        HTMLFileLogging log;

        #endregion

        #region event handler event trapping
        /// <summary>
        /// The sharepoint event for ItemAdded
        /// </summary>
        /// <param name=”properties”></param>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            //run the default event handlers on the item
            base.ItemAdded(properties);

            //create the log handler object
            log = new HTMLFileLogging(c_logFileFolder, string.Format(LogFileName,properties.ListTitle,properties.OpenWeb().Title) , true, false);
            this.WriteToLog(“ItemAdded was triggered”,true);
            //if in debug mode, write all the properties in the item to the log
            if(DEBUG_MODE)
                WriteItemPropertiesToLog(properties.ListItem);
            
            this.WriteToLog(“Setting permissions”, true);
            try
            {
                //impersonate an administrator who can change permissions on list items in the list
                ImpersonationUtility imp = ImpersonationUtility.ImpersonateAdmin();
                //open the spweb object to get the token for the user
                using (SPWeb webOrigUser = properties.OpenWeb())
                {
                    //get the token for the impersonation user (this will get the user that the ImpersonationUtility is using)
                    SPUserToken token = webOrigUser.AllUsers[WindowsIdentity.GetCurrent().Name].UserToken;
                    //reopen the spweb object with the new token – full impersonation!
                    using (SPSite site = new SPSite(properties.SiteId, token))
                    {
                        using (SPWeb web = site.OpenWeb(properties.RelativeWebUrl))
                        {

                            //call the function that changes the permissions on the list item. 
                            //Do not use properties.ListItem since that will break impersonation!
                            SetAuthorAsOnlyEditor(web.Lists[properties.ListId].GetItemById(properties.ListItemId));
                        }
                    }
                }

                
            }
            catch (Exception ex)
            {
                this.WriteToLog(“Setting permissions encountered an error: ” + ex.Message + Environment.NewLine + ex.ToString(), true);
            }
        }
        
        #endregion

        #region custom functions
        /// <summary>
        /// Loops over the item properties and prints them to the log file. should only be called in debug mode!
        /// </summary>
        /// <param name=”item”>the list item that is currently handled</param>
        private void WriteItemPropertiesToLog(SPListItem item)
        {
            this.WriteToLog(“Item Properties:”,false);
            foreach(SPField field in item.Fields)
            {
                try
                {
                    this.WriteToLog(field.Title + ” : ” + item[field.InternalName].ToString(), false);
                }
                catch { }
            }            
        }
        /// <summary>
        /// Function sets the permission on the list item so that the author has edit permission on the item, 
        /// and all other people with access to the document library can only read.
        /// Relies on the values in the constants c_EditorPermissions and c_ReaderPermissions.
        /// </summary>
        /// <param name=”item”>the list item that is currently handled</param>
        private void SetAuthorAsOnlyEditor(SPListItem item)
        {
            
            using (SPWeb currentWeb = item.Web)
            {
                this.WriteToLog(“Getting author from item”, true);
                //get the author from the item. ‘Author’ is a built-in property, so it should be in all lists.
                string authorValue = item[“Author”].ToString();                
                SPFieldUserValue authorUserValue = new SPFieldUserValue(currentWeb, authorValue);
                SPUser authorUser = authorUserValue.User;
                this.WriteToLog(“Got author name:'” + authorUser.Name + “‘, email: ‘” + authorUser.Email + “‘”, true);
                
                this.WriteToLog(“Breaking role inheritance for the item”, true);                
                //break the security of the item from the list, but keep the permissions
                item.BreakRoleInheritance(true);
                //change the permissions of everyone with access to this item so they are readers only (c_ReaderPermissions)
                ChangeItemExistingRoles(item);

                this.WriteToLog(“Creating role ‘” + c_AuthorRoleName + “‘ in the site if needed”, true);
                //create a security definition in the web for an author-editor
                SPRoleDefinition def = CreateRoleInSite(currentWeb,c_AuthorRoleName,c_EditorPermissions);
                this.WriteToLog(“Assigning role to the user”, true);
                //Set the author user with the permissions defined
                SPRoleAssignment authorRole = new SPRoleAssignment(authorUser.LoginName, authorUser.Email, authorUser.Name, authorUser.Notes);
                this.WriteToLog(“Binding the role assignment of the user to the definition”, true);
                authorRole.RoleDefinitionBindings.Add(def);
                this.WriteToLog(“Adding the role to the item”, true);
                item.RoleAssignments.Add(authorRole);
                this.WriteToLog(“Updating the item”, true);
                item.Update();
                this.WriteToLog(“Success!”, true);
            }
        }
        /// <summary>
        /// This function will make everyone with access to the item a reader.
        /// Loops over all the roles that exist in the item, removes the bindings and adds the reader permission definition to them
        /// </summary>
        /// <param name=”item”>the list item currently handled</param>
        private void ChangeItemExistingRoles(SPListItem item)
        {
            //get, and if necessary create, the reader role
            SPRoleDefinition readerDef = CreateRoleInSite(item.Web, c_ReaderRoleName, c_ReaderPermissions);

            
            foreach (SPRoleAssignment roleAssignment in item.RoleAssignments)
            {
                //delete the existing permissions
                roleAssignment.RoleDefinitionBindings.RemoveAll();
                //add the reader permission
                roleAssignment.RoleDefinitionBindings.Add(readerDef);
                roleAssignment.Update();
                item.Update();

            }
        }
        /// <summary>
        /// Gets and if necessary creates the role in the site.
        /// </summary>
        /// <param name=”web”>The site where the role should be created</param>
        /// <param name=”roleName”>The name of the role to create</param>
        /// <param name=”permissions”>The permission set to give the role. Example: SPBasePermissions.EditListItems | SPBasePermissions.ViewListItems</param>
        /// <returns></returns>
        private SPRoleDefinition CreateRoleInSite(SPWeb web,string roleName,SPBasePermissions permissions)
        {
            this.WriteToLog(“Checking if role ‘”+roleName+”‘ exists in the web”, true);
            //check that the role exists
            if (RoleExists(web, roleName))
            {
                this.WriteToLog(“Role exists in the web”, true);
                //role exists – return it
                return web.RoleDefinitions[roleName];
            }
            else
            {
                //role does not exist in the site-  create it and return.
                this.WriteToLog(“Role does not exist in the web. creating a new role”, true);
                //Create the role definition in the web by the name specified in c_AuthorRoleName
                SPRoleDefinition def = new SPRoleDefinition();
                def.BasePermissions = permissions;
                def.Name = roleName;
                this.WriteToLog(“Adding the role to the FirstUniqueRoleDefinitionWeb”, true);
                web.FirstUniqueRoleDefinitionWeb.RoleDefinitions.Add(def);
                this.WriteToLog(“Updating the web”, true);
                web.FirstUniqueRoleDefinitionWeb.Update();
                web.FirstUniqueRoleDefinitionWeb.Dispose();
                this.WriteToLog(“Reopening the current web object”, true);
                web = web.Site.OpenWeb();
                this.WriteToLog(“Verifying role is in current web”, true);
                if (RoleExists(web, roleName))
                    return web.RoleDefinitions[roleName];
                else
                {
                    throw new Exception(“Role does not exist?”);
                }

            }
        }
        /// <summary>
        /// This function checks the spweb objec to see if a specific role exists (by name)
        /// </summary>
        /// <param name=”web”>the spweb object for the site to contain the role.</param>
        /// <param name=”roleName”>the name of the role searched for</param>
        /// <returns></returns>
        private bool RoleExists(SPWeb web, string roleName)
        {
            this.WriteToLog(“Loading the RoleDefinitions xml string:”, true);
            this.WriteToLog(web.RoleDefinitions.Xml, true);
            //read the xml of the roledefinitions
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(web.RoleDefinitions.Xml);
            this.WriteToLog(“Searching for the role in the xml”, true);
            //search for the role with the name in the xml
            XmlNode node = doc.SelectSingleNode(“//Role[@Name='”+roleName+”‘]”);
            //if the search returned null, the role does not exist
            if (node == null)
                return false;
            else
                return true;
        }
        /// <summary>
        /// writes a message to the log file
        /// </summary>
        /// <param name=”message”>The message to write</param>
        /// <param name=”debugOnly”>If true, the message will only get written when the code runs in debug mode.</param>
        private void WriteToLog(string message,bool debugOnly)
        {
            if (DEBUG_MODE || !debugOnly)
                log.WriteToLogFile(message);            
        }
        #endregion
    }
    /// <summary>
    /// Handles simple file logging. Recommend switching to trace log.
    /// </summary>
    class HTMLFileLogging
    {
        #region class properties
        private string logFolderPath = @”c:\logs”;
        public string LogFolderPath
        {
            get
            {
                return logFolderPath;
            }
            set
            {
                if (Directory.Exists(value))
                {
                    logFolderPath = value;
                    if (logFolderPath.EndsWith(“\\”))
                    {
                        logFolderPath = logFolderPath.Remove(logFolderPath.Length);
                    }
                }
                else
                {
                    throw new DirectoryNotFoundException();
                }
            }
        }
        private string logFileName = “”;
        public string LogFileName
        {
            get
            {
                return logFileName;
            }
            set
            {
                logFileName = value;
            }
        }
        public string LogFilePath
        {
            get
            {
                return this.LogFolderPath + “\\” + this.LogFileName;
            }
        }
        
        #endregion
        
        #region CTOR
        /// <summary>
        /// Create a HTMLFileLogging object
        /// </summary>
        /// <param name=”folderPath”>The path of the folder that will hold the log file (no file name)</param>
        /// <param name=”fileName”>The name of the file to create</param>
        /// <param name=”createPath”>When this is set to true and the folder does not exist, the code will create the folder.</param>
        /// <param name=”deleteFile”>When this is set to true and the file exists, the code will delete the file and create a new one</param>
        public HTMLFileLogging(string folderPath, string fileName, bool createPath, bool deleteFile)
        {
         
            this.LogFileName = fileName;
            
            if (createPath && !Directory.Exists(folderPath))
            {
                Directory.CreateDirectory(folderPath);
            }
            this.LogFolderPath = folderPath;
            if (File.Exists(this.LogFilePath) && deleteFile)
            {
                File.Delete(this.LogFilePath);
            }

        }

        #endregion

        #region custom code
        /// <summary>
        /// Writes a string to the log file. 
        /// </summary>
        /// <param name=”message”>a string to write. supports html tags.</param>
        public void WriteToLogFile(string message)
        {
            try
            {
                StreamWriter sw = new StreamWriter(this.LogFilePath,true);
                sw.WriteLine(“<p>”);
                sw.WriteLine(“<date>” + DateTime.Now.ToShortDateString()+ “</date> <time>” + DateTime.Now.ToLongTimeString() + “</time> <br /> <message>” + message + “</message>”);
                sw.WriteLine(“</p>”);
                sw.Flush();
                sw.Close();
            }
            catch (Exception ex)
            {
            }
        }

        #endregion

    }
    /// <summary>
    /// Thanks to impersonation example of Victor Vogelpoel [Macaw] 
    /// http://dotnetjunkies.com/WebLog/victorv/archive/category/2032.aspx
    /// </summary>
    public sealed class ImpersonationUtility
    {        
        private static string ADMINDOMAINACCOUNT = @”domain\user”;//CHANGE THIS!
        private static string ADMINDOMAIN = “domain”;//CHANGE THIS!
        private static string ADMINACCOUNT = “user”;//CHANGE THIS!
        private static string ADMINPASSWORD = “password”;//CHANGE THIS!
        private WindowsImpersonationContext _wiContext;
        public IntPtr token;
        /// <summary>
        /// Private ctor.
        /// </summary>
        private ImpersonationUtility()
        { }
        /// <summary>
        /// Start impersonating the administrator.
        /// </summary>
        /// <returns>an ImpersonationUtility instance.</returns>
        public static ImpersonationUtility ImpersonateAdmin()
        {
            ImpersonationUtility imp = new ImpersonationUtility();
            imp._ImpersonateAdmin();
            return imp;
        }
        /// <summary>
        /// Undo the impersonation.
        /// </summary>
        public void Undo()
        {
            if (this._wiContext != null)
            {
                this._wiContext.Undo();
                this._wiContext = null;
            }
        }
        private void _ImpersonateAdmin()
        {
            token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;
            try
            {
                // Only start admin impersonation if we’re not the admin…
                if (String.Compare(ADMINDOMAINACCOUNT, WindowsIdentity.GetCurrent().Name, true, CultureInfo.InvariantCulture) != 0)
                {
                    // Temporarily stop the impersonation started by Web.Config.
                    // WindowsIdentity.Impersonate() will store the current identity (the
                    // account of the requestor) and return to the account of the ApplicationPool
                    // which is “DOMAIN\SPAdmin”.
                    this._wiContext = WindowsIdentity.Impersonate(IntPtr.Zero);
                    // But somehow the reverted account “DOMAIN\SPAdmin” still does
                    // not have enough privileges to access SharePoint objects, so
                    // we’re logging in DOMAIN\SPAdmin again…
                    if (NativeMethods.LogonUserA(ADMINACCOUNT, ADMINDOMAIN, ADMINPASSWORD, NativeMethods.LOGON32_LOGON_INTERACTIVE,
                    NativeMethods.LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                    {
                        if (NativeMethods.DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                        {
                            WindowsIdentity wi = new WindowsIdentity(tokenDuplicate);
                            // NOTE: Impersonate may fail if account that tries to impersonate does
                            // not hold the “Impersonate after Authentication” privilege
                            // See local security policy – user rights assignment.
                            // Note that the ImpersonationContext from the Impersonate() call
                            // is ignored. Upon the Undo() call, the original account
                            // will be reinstated.
                            wi.Impersonate();
                        }
                        else
                        {
                            throw new Win32Exception(Marshal.GetLastWin32Error(),
                            “Impersonation: Error duplicating token after logon for user \”DOMAIN\\SPAdmin\””);
                        }
                    }
                    else
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error(),
                        “Impersonation: Error logging on user \”DOMAIN\\SPAdmin\””);
                    }
                }
            }
            finally
            {
                if (token != IntPtr.Zero)
                    NativeMethods.CloseHandle(token);
                if (tokenDuplicate != IntPtr.Zero)
                    NativeMethods.CloseHandle(tokenDuplicate);
            }
        }
    }
    /// <summary>
    /// Thanks to impersonation example of Victor Vogelpoel [Macaw] 
    /// http://dotnetjunkies.com/WebLog/victorv/archive/category/2032.aspx
    /// </summary>
    internal sealed class NativeMethods
    {
        private NativeMethods() { }

        [DllImport(“kernel32.dll”, CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        public const int LOGON32_PROVIDER_DEFAULT = 0;
        public const int LOGON32_LOGON_INTERACTIVE = 2;
        public const int LOGON32_LOGON_NETWORK = 3;

        [DllImport(“advapi32.dll”)]
        public static extern int LogonUserA(String lpszUserName,
        String lpszDomain,
        String lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken);

        [DllImport(“advapi32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int DuplicateToken(IntPtr hToken,
        int impersonationLevel,
        ref IntPtr hNewToken);

        [DllImport(“advapi32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool RevertToSelf();
    } 
}

Your tenant administrator has to approve this app.

Even if the logged in user is the Global Administrator as well as Site Collection Administrator and also the user has Full Control of this Site, it displays the same error.

Resolution:

 

2016-12-09_14-25-17

From the Site contents page, go to the app which your are debugging and click on ellipsis (“…”) or context navigation.

2016-12-09_14-27-47

2016-12-09_14-28-30

Now run the app from the site contents page, and you will be able to run the app in debug mode (from localhost).